If we prefer to use classes, we can use the class-based components API that comes with Vue.
In this article, we’ll look at how to developing Vue apps with class-based components.
TypeScript Autocomplete for External Hooks
We can add autocomplete for external hooks within our class-based components written in TypeScript.
For instance, we can write:
vue-router-hook-types.ts
import Vue from "vue";
import { Route, RawLocation } from "vue-router";
declare module "vue/types/vue" {
interface Vue {
beforeRouteEnter?(
to: Route,
from: Route,
next: (to?: RawLocation | false | ((vm: Vue) => void)) => void
): void;
beforeRouteLeave?(
to: Route,
from: Route,
next: (to?: RawLocation | false | ((vm: Vue) => void)) => void
): void;
beforeRouteUpdate?(
to: Route,
from: Route,
next: (to?: RawLocation | false | ((vm: Vue) => void)) => void
): void;
}
}
main.ts
import Vue from "vue";
import App from "./App.vue";
import Foo from "./views/Foo.vue";
import Bar from "./views/Bar.vue";
import VueRouter from "vue-router";
import "./vue-router-hook-types";
Vue.config.productionTip = false;
const routes = [
{ path: "/foo", component: Foo },
{ path: "/bar", component: Bar }
];
const router = new VueRouter({
routes
});
Vue.use(VueRouter);
new Vue({
router,
render: (h) => h(App)
}).$mount("#app");
App.vue
<template>
<div id="app">
<router-link to="/foo">Foo</router-link>
<router-link to="/bar">Bar</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "App",
};
</script>
views/Bar.vue
<template>
<div>bar</div>
</template>
<script>
import Vue from "vue";
import Component from "vue-class-component";
Component.registerHooks([
"beforeRouteEnter",
"beforeRouteLeave",
"beforeRouteUpdate",
]);
@Component
export default class Foo extends Vue {
beforeRouteEnter(to, from, next) {
console.log("beforeRouteEnter");
next();
}
beforeRouteUpdate(to, from, next) {
console.log("beforeRouteUpdate");
next();
}
beforeRouteLeave(to, from, next) {
console.log("beforeRouteLeave");
next();
}
}
</script>
views/Foo.vue
<template>
<div>foo</div>
</template>
<script>
import Vue from "vue";
import Component from "vue-class-component";
import "vue-class-component/hooks";
Component.registerHooks([
"beforeRouteEnter",
"beforeRouteLeave",
"beforeRouteUpdate",
]);
@Component
export default class Foo extends Vue {
beforeRouteEnter(to, from, next) {
console.log("beforeRouteEnter");
next();
}
beforeRouteUpdate(to, from, next) {
console.log("beforeRouteUpdate");
next();
}
beforeRouteLeave(to, from, next) {
console.log("beforeRouteLeave");
next();
}
}
</script>
We have the vue-router-hook-types.ts
with the type definitions for the Vue Router hooks.
In main.ts
, we have:
import "./vue-router-hook-types";
to import the type definitions.
Then in the Foo.vue
and Bar.vue
components, we can see the beforeRouteEnter
, beforeRouteUpdate
, and beforeRouteLeave
hooks in the autocomplete menu when we’re typing them into the component class code.
We can also annotate types of methods in our code.
For instance, we can write:
<template>
<div>
<button @click="increment">increment</button>
<p>{{ count }}</p>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";
@Component(({
watch: {
count(val: number) {
this.log(val)
}
}
})
export default class HelloWorld extends Vue {
count: number = 0
log(val: number): void {
console.log(val)
}
increment(){
this.count++
}
}
</script>
We have the log
method that returns void
and takes a val
parameter with type number
,
We use that in the count
watcher which is defined in the argument we pass into Component
.
This way, we won’t have to worry about passing parameters with data types we don’t expect.
And the same applies to return types of methods.
Conclusion
We can annotate data types easily with TypeScript to avoid making mistakes in our Vue class-based components.